package cn.sxy.mybatis.builder.xml;

import cn.sxy.mybatis.builder.BaseBuilder;
import cn.sxy.mybatis.datasource.DataSourceFactory;
import cn.sxy.mybatis.io.Resources;
import cn.sxy.mybatis.mapping.BoundSql;
import cn.sxy.mybatis.mapping.MappedStatement;
import cn.sxy.mybatis.mapping.SqlCommandType;
import cn.sxy.mybatis.mapping.Environment;
import cn.sxy.mybatis.session.Configuration;
import cn.sxy.mybatis.transaction.TransactionFactory;
import cn.sxy.mybatis.type.TypeAliasRegistry;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class XMLConfigBuilder extends BaseBuilder {

    private  Element root;

    public XMLConfigBuilder(Reader reader) {
        super(new Configuration());
        //dom4j的SAXReader解析器处理xml
        SAXReader saxReader = new SAXReader();
        saxReader.setValidation(false); // 禁用 DTD 验证--不会联网加载
        saxReader.setEntityResolver((publicId, systemId) -> new InputSource(new java.io.StringReader("")));
        try{
            Document document = saxReader.read(new InputSource(reader));//解析xml得到文档对象
            //得到根节点（<configuration>），保存到 root 变量中，后续会逐步解析其中的 <environments>、<mappers> 等节点。
            root = document.getRootElement();

        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
    }

    /***
     * 调用顺序固定：先解析 <environments> 数据源配置，再解析 <mappers> SQL 映射文件；
     *
     * 返回最终构建的 Configuration 对象。
     * @return
     */
    public Configuration parse() {
        try {
            //以<configuration>开头和结尾的整个xml内容
            System.out.println("Root XML 内容为：\n" + root.asXML());

            // 环境
            environmentsElement(root.element("environments"));

            // 解析映射器
            mapperElement(root.element("mappers"));
        } catch (Exception e) {
            throw new RuntimeException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
        }
        return configuration;

    }


    /***
     *     <mappers>
     *         <mapper resource="mapper/User_Mapper.xml"/>
     *     </mappers>
     *     获取mapper
     * @param mappers
     * @throws Exception
     */
    private void mapperElement(Element mappers) throws Exception {
        List<Element> mapperList = mappers.elements("mapper");

//        for (Element e : mapperList) {
//            String resource=e.attributeValue("resource");
//            Reader reader = Resources.getResourcesAsReader(resource);
//            SAXReader saxReader = new SAXReader();
//            Document document = saxReader.read(new InputSource(reader));
//            Element root = document.getRootElement();
//
//            //命名空间
//            String namespace = root.attributeValue("namespace");
//
//            List<Element> selectNodes = root.elements("select");
//            for(Element node : selectNodes){
//                String id=node.attributeValue("id");
//                String parameterType=node.attributeValue("parameterType");
//                String resultType=node.attributeValue("resultType");
//                String sql=node.getText();
//
//                //匹配
//                HashMap<Integer, String> parameter = new HashMap<>();
//
//                // 处理占位符 #{param} → ?
//                //处理后 SQL 如：select * from user where id = ?
//                Pattern pattern=Pattern.compile("(#\\{(.*?)})");
//                Matcher matcher = pattern.matcher(sql);
//                for (int i = 0; matcher.find(); i++) {
//                    String g1=matcher.group(1); //#{id}
//                    String g2=matcher.group(2); //id
//                    parameter.put(i,g2);  //parameter 是参数顺序映射表 {0=id}
//                    sql=sql.replace(g1,"?");
//                }
//
//                String msId=namespace+"."+id;
//                String nodeName=node.getName();
//                SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
//
//                BoundSql boundSql = new BoundSql(sql, parameter, parameterType, resultType);
//
////                MappedStatement mappedStatement = new MappedStatement.Builder(configuration, msId, sqlCommandType, boundSql).build();
//
//                MappedStatement mappedStatement = MappedStatement.builder()
//                        .configuration(configuration)
//                        .id(msId)
//                        .sqlCommandType(sqlCommandType)
//                        .boundSql(boundSql)
//                        .build();
//                // 添加解析 SQL
//                configuration.addMappedStatement(mappedStatement);
//        Class<?> mapperClass = Class.forName(namespace);
//        configuration.addMapper(mapperClass);
        for (Element e : mapperList) {
            String resource = e.attributeValue("resource");
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 在for循环里每个mapper都重新new一个XMLMapperBuilder，来解析
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource);
            mapperParser.parse();
        }

    }

    private void environmentsElement(Element context) throws Exception {

        String environment=context.attributeValue("environment");
        List<Element> environments = context.elements("environment");
        for (Element e : environments) {

            //事务管理
            TransactionFactory txFactory = (TransactionFactory) typeAliasRegistry.resolveAlias(e.element("transactionManager").attributeValue("type")).newInstance();

            // 数据源
            Element dataSourceElement = e.element("dataSource");
            DataSourceFactory dataSourceFactory = (DataSourceFactory) typeAliasRegistry.resolveAlias(dataSourceElement.attributeValue("type")).newInstance();
            List<Element> propertyList = dataSourceElement.elements("property");
            Properties props = new Properties();
            for (Element property : propertyList) {
                props.setProperty(property.attributeValue("name"), property.attributeValue("value"));
            }
            dataSourceFactory.setProperties(props);
            DataSource dataSource = dataSourceFactory.getDataSource();
            String id=e.attributeValue("id");

            // 构建环境
            Environment environmentBuilder =Environment.builder()
                    .id(id)
                    .dataSource(dataSource)
                    .transactionFactory(txFactory).build();


            configuration.setEnvironment(environmentBuilder);


        }
    }
}
